package com.yufubao.framework.exception;

import cn.dev33.satoken.exception.NotLoginException;
import com.yufubao.framework.enums.CommonExceptionEnum;
import com.yufubao.framework.result.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Description:
 * 全局异常捕获类
 * 所有的异常都会在这个类中处理
 *
 * @author zhangzhan
 * @version 1.0
 * @date 2020/1/22 20:50
 * @since JDK 1.8
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
 
    /**
     * 捕获自定义的几种异常
     *
     * @param ex
     * @return 异常码和异常信息封装的ResultData对象
     */
    @ExceptionHandler(value = BaseException.class)
    public ResponseResult handlerBizException(Exception ex){
 
        // 向下转型使BizException的自定义的不同于父类Exception的方法可以使用
        BaseException baseException = (BaseException)ex;
 
        // 获得异常码和异常信息
        int exCode = baseException.getErrorCode();
        String exMsg = baseException.getMessage();
 
        // 将异常码和异常信息封装成通用数据返回类型
        ResponseResult resultData = ResponseResult.errorResult(exCode, exMsg);
 
        // 对异常做日志记录，方便项目正式运行时发生异常后寻找异常发生点
        log.error(exCode + ":" +exMsg, baseException);
 
        // 向前端返回数据
        return resultData;
    }


    //JS303校验异常
    @ResponseStatus(HttpStatus.PRECONDITION_REQUIRED)
    @ExceptionHandler(BindException.class)
    public ResponseResult bindExceptionHandler(BindException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List<String> msgList = fieldErrors.stream()
                .map(o -> o.getDefaultMessage())
                .collect(Collectors.toList());
        String messages = StringUtils.join(msgList.toArray(), ";");
        log.error("Validation格式校验异常:-------------->{}",messages);
        return ResponseResult.errorResult(CommonExceptionEnum.VALID_EXCEPTION.getCode(), messages);
    }


 
    /**
     * 系统抛出的异常
     * @param ex
     * @return 固定异常码10002 和 异常信息封装的ResultData对象
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseResult handlerException(Exception ex){
 
        // 对所以其他异常，统一异常码为10002，并封装
        ResponseResult resultData = ResponseResult.errorResult(5001,ex.getMessage());
 
        // 日志记录
        log.error(5001 + ":" +ex.getMessage(),ex);
 
        // 返回数据
        return resultData;
    }


    /**
     * 登录异常
     * @param ex
     * @return
     */
    @ExceptionHandler(value = NotLoginException.class)
    public ResponseResult notLoginException(NotLoginException ex){

        ResponseResult resultData = ResponseResult.errorResult(CommonExceptionEnum.NOT_PERMISSION);

        // 日志记录
        log.error(CommonExceptionEnum.NOT_PERMISSION.getCode() + ":" +ex.getMessage(),ex);

        // 返回数据
        return resultData;
    }
 
}